import { HttpClient } from '@angular/common/http';

import { GisDataUtils } from 'src/app/base/gis/data/gis.data';
import { GisPointSearchUtils } from 'src/app/base/gis/search/gis.point.search';

declare var form: any;
declare var map: any;

/**
 * 定义GIS地图加载辅助类
 */
export class GisMapUtils {
    // 树数据处理对象
    ts: any;
    // 当前地图对象
    pmap: any;
    // 地图方案
    maps: any = [];
    // 当前地图方案
    curMap: any = '';
    // 是否加载中
    isLoading = false;
    // 图层数据
    LayerDatas: any[] = [{}];
    // 展开数据缓存
    expandDataCache: any[] = [];
    // 是否全部展开
    expandAll = false;
    // 当前search对象
    search: any;

    // 初始化
    init(http: HttpClient) {
        this.isLoading = true;
        // 第一步，获取推荐方案
        GisDataUtils.getMap(http, (datas) => {
            // 第二步，选择一个方案
            if (datas.data) {
                this.maps = datas.data;
                this.curMap = this.maps[0].id;
            } else {
                this.maps = [];
                this.curMap = '';
            }
            // 第三步，获取地图方案参数
            this.getMapParas(http);
        }, () => { });

        window.addEventListener('resize', () => {
            if (this.pmap) {
                this.pmap.resize();
            }
        });
    }

    // 切换地图方案
    setMap(http: HttpClient, m: string) {
        this.curMap = m;
        this.getMapParas(http);
    }

    // 第三步，获取地图方案参数
    private getMapParas(http: HttpClient) {
        this.ts = new form.TreeService();
        GisDataUtils.getLayers(http, this.curMap, (res) => {
            if (res.code === '-1') {
                // 第四步，初始化地图
                this.initMap(res.data);
                form.ConfigService.mapParas = res.data;
                // 第五步，初始化图层列表
                const data = this.getAll(res.data.layers);
                this.oParent(data);
                this.checkData(data);
                this.changeLayer(data);
                this.LayerDatas = data;
                this.expandDataCache = this.ts.getExpandData(data, this.expandAll);
            }
            this.isLoading = false;
        }, (error) => {
            this.isLoading = false;
        });
    }

    // 第四步，初始化地图
    private initMap(data: any) {
        const surl = 'fm://styles/style/' + this.curMap;

        if (this.pmap) {
            this.pmap.setStyle(surl);
            if (this.search) {
                this.search.clear();
            }
            return;
        }

        const z = data.zoom;
        const mz = data.maxZoom;
        const iz = data.minZoom;
        const scenter = JSON.parse(data.center);
        const sextent = JSON.parse(data.extent);

        map.Factory.create('mapui', {
            // 自定义样式
            style: surl,
            center: scenter,
            zoom: z,
            maxZoom: mz,
            minZoom: iz,
            strategy: ['mapboxgl'],
            fullExtent: sextent,
            // 比例尺控件
            controls: ['Scale', 'Navigation'],
            preserveDrawingBuffer: true
        }, (p) => {
            form.ConfigService.map = p;

            this.pmap = p;
            form.ConfigService.measure = map.Factory.Measure();

            // 鼠标移动事件绑定
            this.pmap.on('mousemove', (o: any) => {
                document.getElementById('positionInfo').innerHTML = (o.lngLat.lng.toFixed(3) + ' , ' + o.lngLat.lat.toFixed(3));
            });

            // 初始化查询接口
            this.search = new GisPointSearchUtils();
            this.search.init();

            // 执行全局函数加载点查询数据
            form.ConfigService.loadPointSearch(this.search);
        });
    }

    private getAll(layserDatas: any) {
        const treeDatas = [];
        const oneLevel = this.getChild(layserDatas, '0');
        if (oneLevel != null && oneLevel.length > 0) {
            if (oneLevel != null && oneLevel.length > 0) {
                oneLevel.forEach(data => {
                    treeDatas.push(data);
                    this.addNext(layserDatas, data);
                });
            }
        }
        return treeDatas;
    }

    private getChild(datas: any, pid: string) {
        const resDatas = [];
        datas.forEach(data => {
            if (data.pid === pid) {
                resDatas.push(data);
            }
        });

        // 排序
        resDatas.sort((a: any, b: any) => {
            return a.listOrder - b.listOrder;
        });
        return resDatas;
    }

    private addNext(layserDatas: any, item: any) {
        const nextLevel = this.getChild(layserDatas, item.id);
        if (nextLevel != null && nextLevel.length > 0) {
            nextLevel.forEach(data => {
                this.addNext(layserDatas, data);
            });
            item.children = nextLevel;
        }
    }

    private expand(item) {
        this.ts.expand(item);
    }

    // 处理数据的parent
    private oParent(data) {
        if (data && data.length > 0) {
            data.forEach(item => {
                this.oParentForChild(item);
            });
        }
    }

    private oParentForChild(data) {
        if (data.children && data.children.length > 0) {
            data.children.forEach(cItem => {
                cItem.parent = data;
                this.oParentForChild(cItem);
            });
        }
    }

    // 如果存在一个子节点它的子节点全部为不显示，则把这个子节设置为left = true
    private checkData(data) {
        if (data && data.length > 0) {
            data.forEach(item => {
                this.checkDataForChild(item);
            });
        }
    }

    private checkDataForChild(data) {
        const children = data.children;
        // 数据有子集才需要修改其状态，没有子集则为配置好的状态
        if (children && children.length > 0) {
            data.leaf = this.changeShowState(children);
            data.checked = this.changeCheckState(children);
            children.forEach(item => {
                this.checkDataForChild(item);
            });
        }
    }

    private changeShowState(children: any) {
        let result = true;

        children.forEach(item => {
            if (item.show === true) {
                result = false;
            }
        });

        return result;
    }

    private changeCheckState(children: any) {
        let result = false;

        children.forEach(item => {
            if (item.checked === true) {
                result = true;
            }
        });

        return result;
    }

    private changeLayer(data: any) {
        if (form.ConfigService.map) {
            this.oChecked(data);
        } else {
            setTimeout(() => {
                if (form.ConfigService.map) {
                    this.oChecked(data);
                } else {
                    this.changeLayer(data);
                }
            }, 100);
        }
    }

    // 处理数据中选中的显示图层
    private oChecked(data) {
        if (data && data.length > 0) {
            data.forEach(item => {
                this.oCheckedItem(item);
                this.oCheckedForChild(item);
            });
        }
    }

    private oCheckedForChild(data) {
        if (data.children && data.children.length > 0) {
            data.children.forEach(cItem => {
                this.oCheckedItem(cItem);
                this.oCheckedForChild(cItem);
            });
        } else {
            this.oCheckedItem(data);
        }
    }

    private oCheckedItem(item) {
        if (item.leaf) {
            this.checkChange(item, item.checked);
        }
    }

    private checkChange(item: any, checked: boolean) {
        const visibility = checked ? 'visible' : 'none';
        if (item.children && item.children.length > 0) {
            item.children.forEach((ci: any) => {
                form.ConfigService.map.getMap().setLayoutProperty(ci.id, 'visibility', visibility);
                this.checkChange(ci, checked);
            });
        } else {
            form.ConfigService.map.getMap().setLayoutProperty(item.id, 'visibility', visibility);
        }
    }

    // 选中
    check(item) {
        if (item.checked) {
            if (item.selected) {
                item.selected = false;
            }
            this.checkChange(item, false);
        } else {
            if (item.selected) {
                item.selected = false;
            } else {
                this.ts.select(item, this.LayerDatas);
            }
            this.checkChange(item, true);
        }
    }

}
